home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-19
/
intrlib1.zip
/
MOUSEDRV.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-03-10
|
14KB
|
379 lines
/******************************************************************************
* Iteraction library - windows. *
* *
* Written by Gershon Elber, Oct. 1990 *
*******************************************************************************
* W A R N I N G : This module assumes mouse driver was installed using *
* one of the following program: mouse.com or mouse.sys. *
* *
* This module can be compiled in any model (tiny..huge) *
* *
* The following routines are available: *
* 1. MouseSetResolution(int Resolution) - set mouse rosolution. *
* 2. MouseDetect() - returns TRUE if mouse detected in system. *
* 3. MouseInit() - must be called first before any other call. *
* 4. MouseShowCorsur() - show mouse cursor. *
* 5. MouseHideCorsur() - hide mouse cursor. *
* 6. MouseSetPosition() - set mouse XY position. *
* 7. MouseQueryBuffer() - returns event ring buffer status. *
* 8. MouseQueryDataBuffer() - returns event ring buffer data status. *
* 9. MouseGetBuffer() - returns next event from ring buffer. *
* 10.MouseFlushBuffer() - clear all data currently in buffer. *
* 11.MouseClose() - must be called last before application program dies. *
* *
* Note that as the mouse driver is used asyncronically (i.e. interrupts) *
* fail to call MouseInit() at the begining or even worse, call *
* MouseClose() in the end is an invitation for total system disaster! *
* *
* Written by: Gershon Elber IBM PC Ver 0.1, Sep. 1988 *
* *
* Ver 0.2 - No interrupt vector is used (MouseHandler is called directly). *
******************************************************************************/
/* #define DEBUG * Uncomment it for simple test routine. */
#include <dos.h>
#include <stdio.h>
#include "MouseDrv.h"
#ifdef DEBUG
#include <conio.h>
#endif DEBUG
#define ABS(x) ((x) > 0 ? (x) : (-(x)))
/* Two external integers defined Mouse Range (start from 0): */
int MSMouseXmax = 1000,
MSMouseYmax = 1000;
static int BufferHead, BufferTail, BufferFull, /* Implement ring buffer. */
BufferOverRun, /* Over run error in mouse buffer. */
MouseBuffer[BUFFER_SIZE][2], /* Mouse event to save. */
WasMouseSetUp = FALSE, /* TRUE - mouse successfully installed. */
SkipMouseEvents = 1; /* Number of move events to skip + 1. */
static struct SREGS SRegs;
static void MouseSysCall(int Func, int *m2, int *m3, int *m4);
/**************************************************************************
* Static routine that is used to save DS register, so it can be restore *
* when the Mouse Handler is invoked. This routine is used only to *
* allocate space in the code segment for one integer (DS), and is never *
* been called. If you have better solution how to restore DS let me know! *
**************************************************************************/
static void far SaveDSOnThisRoutine(void)
{
SRegs.ds = _DS; /* Looks like something useful - its NOT! */
}
/**************************************************************************
* Set resolution for mouse. *
**************************************************************************/
void MouseSetResolution(int Resolution)
{
MSMouseXmax = MSMouseYmax = Resolution;
}
/**************************************************************************
* Mouse detect routine. Does three step test: *
* 1. Test if there is none NULL vector in vector interrupt 0x33 which *
* should hold the mouse driver. *
* 2. Test if that pointer is pointing on IRET instruction or not. *
* 3. Test if the mouse is connected by calling to the mouse driver - *
* sys call 0x00. *
**************************************************************************/
int MouseDetect(void)
{
unsigned char far *Ptr;
union REGS Regs;
/* Look if anything is installed in the mouse interrupt vector: */
if (((Ptr = (unsigned char far *) getvect(0x33)) == NULL) ||
(*Ptr == 0xcf /* IRET */)) return FALSE;
Regs.x.ax = 0; /* Select reset and test function. */
/* interrupt 51 decimal is used by mouse device driver itself: */
int86x(0x33, &Regs, &Regs, &SRegs);
return (Regs.x.ax);
}
/**************************************************************************
* This is the mouse handler itself: called from mouse driver on events. *
* The x, y coordinates are saved as two integers in the buffer as follows:*
* X is positive if Left Button is pressed, Negative otherwise. *
* Y is positive if Right Button is pressed, Negative otherwise. *
* Note 1 is added to X, Y to make them none zero... *
* Also note DS must be restore before data (event buffer) is accessed. *
**************************************************************************/
static void far MouseHandler(void)
{
static int Skip = 0;
int far *RestoreDS = (int far *) SaveDSOnThisRoutine;
int Buttons = _BX, X = _CX, Y = _DX, SaveDS = _DS;
_DS = *RestoreDS;
if (Skip++ < SkipMouseEvents && !Buttons) return;
Skip = 0;
if (BufferFull)
BufferOverRun = TRUE; /* Buffer overflow. */
else {
if (Buttons > 0x03) Buttons = 0x03;
MouseBuffer[BufferHead][0] = (Buttons & 0x01 ? X+1 : -X-1);
MouseBuffer[BufferHead++][1] = (Buttons & 0x02 ? Y+1 : -Y-1);
if (BufferHead == BUFFER_SIZE) BufferHead = 0;
if (BufferHead == BufferTail) BufferFull = TRUE;
}
_DS = SaveDS;
}
/**************************************************************************
* See all description on all functions available (0-16, 19) on page 54 in *
* Microsoft Mouse manual. *
**************************************************************************/
static void MouseSysCall(int Func, int *m2, int *m3, int *m4)
{
union REGS Regs;
Regs.x.ax = Func; /* Select the requested function. */
Regs.x.bx = *m2;
Regs.x.cx = *m3;
Regs.x.dx = *m4;
/* interrupt 51 decimal is used by mouse device driver itself: */
int86x(0x33, &Regs, &Regs, &SRegs);
*m2 = Regs.x.bx;
*m3 = Regs.x.cx;
*m4 = Regs.x.dx;
}
/**************************************************************************
* Mouse Initialization: return NULL if succesful, else error msg string. *
**************************************************************************/
char *MouseInit(int Sensitivity)
{
int far *SaveDS;
int m2, m3, m4;
if (WasMouseSetUp)
return "MouseInit: Mouse already initialized, ignored.";
if (MSMouseXmax == 0 || MSMouseYmax == 0)
return "MouseInit: Mouse range was not initialized by graphic driver.";
SkipMouseEvents = 0; /* Takes too much time to redraw cursor... */
SRegs.ds = _DS; /* In case the communication with the driver needs that. */
SaveDS = (int far *) SaveDSOnThisRoutine;
*SaveDS = _DS;
BufferHead = BufferTail = 0; /* Reset the Buffer pointers. */
BufferFull = BufferOverRun = FALSE;
MouseSysCall(0, &m2, &m3, &m4); /* Install Mouse. */
m3 = 0;
m4 = MSMouseXmax;
MouseSysCall(7, &m2, &m3, &m4); /* Set Column Range. */
m3 = 0;
m4 = MSMouseYmax;
MouseSysCall(8, &m2, &m3, &m4); /* Set Row Range. */
m3 = Sensitivity;
m4 = Sensitivity;
MouseSysCall(15, &m2, &m3, &m4); /* Set Mickeys Per 8 pixels. */
m3 = 0x2b;/* Set bits 0, 1, 3, 5 - intrpt on mouse move & button pressed.*/
m4 = FP_OFF(MouseHandler);
SRegs.es = FP_SEG(MouseHandler);
MouseSysCall(12, &m2, &m3, &m4); /* Link the MouseHandler() routine. */
WasMouseSetUp = TRUE;
return NULL;
}
/**************************************************************************
* Mouse Closing: *
**************************************************************************/
void MouseClose(void)
{
int m2, m3, m4;
if (!WasMouseSetUp) return; /* Install mouse first! */
m3 = 0x00; /* No interrupts any more... */
MouseSysCall(12, &m2, &m3, &m4);
WasMouseSetUp = FALSE;
}
/**************************************************************************
* Routine returns TRUE if buffer is not empty. *
**************************************************************************/
int MouseQueryBuffer(void)
{
return (BufferFull || BufferHead != BufferTail);
}
/**************************************************************************
* Routine to return Mouse buffer status: *
* Returns TRUE if buffer is not empty. In addition sets X, Y, Buttons to *
* the end of buffer without modifying the buffer, and set OverRunError. *
**************************************************************************/
int MouseQueryDataBuffer(int *X, int *Y, int *Buttons, int *OverRunError)
{
if (BufferFull || BufferHead != BufferTail) {
*X = ABS(MouseBuffer[BufferTail][0]) - 1;
*Y = ABS(MouseBuffer[BufferTail][1]) - 1;
*Buttons = (MouseBuffer[BufferTail][0] > 0 ? 0x01 : 0x00) +
(MouseBuffer[BufferTail][1] > 0 ? 0x02 : 0x00);
*OverRunError = BufferOverRun;
return TRUE;
}
else
return FALSE;
}
/**************************************************************************
* Routine to get one event from buffer. waits for one if buffer empty. *
* Returns OverRun status - TRUE if over run occurs. In addition sets *
* X, Y, Buttons to the end of buffer, and increment. *
**************************************************************************/
int MouseGetBuffer(int *X, int *Y, int *Buttons)
{
/* Wait for event if buffer is empty: */
while (!(BufferFull || BufferHead != BufferTail));
*X = ABS(MouseBuffer[BufferTail][0]) - 1;
*Y = ABS(MouseBuffer[BufferTail][1]) - 1;
*Buttons = (MouseBuffer[BufferTail][0] > 0 ? 0x01 : 0x00) +
(MouseBuffer[BufferTail][1] > 0 ? 0x02 : 0x00);
disable(); /* No interrupts now! */
if (BufferHead == BufferTail) BufferFull = FALSE;
if (++BufferTail == BUFFER_SIZE) BufferTail = 0;
enable(); /* interrupts o.k. now. */
return BufferOverRun;
}
/**************************************************************************
* Routine to flush and clear all the mouse event buffer. *
**************************************************************************/
void MouseFlushBuffer(void)
{
disable(); /* No interrupts now! */
BufferHead = BufferTail;
BufferFull = BufferOverRun = FALSE;
enable(); /* interrupts o.k. now. */
}
/**************************************************************************
* Mouse Show Cursor: *
**************************************************************************/
void MouseShowCursor(void)
{
int m2, x, y;
MouseSysCall(1, &m2, &x, &y); /* Show cursor. */
}
/**************************************************************************
* Mouse Hide Cursor: *
**************************************************************************/
void MouseHideCursor(void)
{
int m2, x, y;
MouseSysCall(2, &m2, &x, &y); /* Hide cursor. */
}
/**************************************************************************
* Mouse Set Position: *
**************************************************************************/
void MouseSetPosition(int X, int Y)
{
int dummy;
MouseSysCall(4, &dummy, &X, &Y); /* Set position. */
}
#ifdef DEBUG
/**************************************************************************
* Routine to make some sound with given Frequency, Time milliseconds: *
**************************************************************************/
void GGTone(int Frequency, int Duration)
{
sound(Frequency);
delay(Duration);
nosound();
}
/**************************************************************************
* Exit routine. *
**************************************************************************/
void MyExit(int ErrCode)
{
exit(ErrCode);
}
/**************************************************************************
* Simple test routine: *
**************************************************************************/
void main(void)
{
int X, Y, Buttons;
if (!MouseDetect()) {
fprintf(stderr, "No mouse was detected, can'nt continue\n");
MyExit(1);
}
MSMouseXmax = 1000;
MSMouseYmax = 1000;
clrscr(); /* Clear screen. */
MouseInit(10); /* Install Mouse. */
MouseShowCursor();
gotoxy (2, 10);
printf("Press any button, or move mouse to get events. Press both buttons to exit.");
do {
while (!kbhit() && !MouseQueryBuffer());
if (kbhit()) break;
if (MouseGetBuffer (&X, &Y, &Buttons)) {
gotoxy(33, 15);
printf("Over Run Error");
MouseFlushBuffer();
sleep(1);
gotoxy(33, 15);
printf(" ");
}
gotoxy(20, 5);
printf("Head = %3d, Tail = %3d, Full = %3d\n",
BufferHead, BufferTail, BufferFull);
gotoxy(16, 1);
if ((Buttons & 0x01) != 0)
printf(" Left ");
else if ((Buttons & 0x02) != 0)
printf("Right ");
else
printf(" No ");
printf("Button was pushed at X=%-3d Y=%-3d", X, Y);
}
while ((Buttons & 0x03) != 0x03); /* Both buttons were pushed. */
MouseHideCursor();
MouseClose();
clrscr(); /* Clear screen. */
}
#endif DEBUG